class Graph {
  float x1, x2, y1, y2;
  //First gonna set max to 4 graphs
  int maxGraphs = 4;
  int numOfGraphs = 0;
  int currentSlot = 0;
  float graphSpace = 12;
  float graphWidth;
  float graphHeight;
  int[] graphType;
  int monthSelected;
  int lastClicked;
  
  String [] genreName = {"Action", "Adventure", "Animation", "Comedy", "Crime", "Documentary", 
  "Drama", "Fantasy", "Family", "Film-Noir", "Horror", "Musical", "Mystery", "Romance", "Sci-Fi", "Thriller", "War", "Western", "All"}; 
  
  String [] monthName={"January","February","March","April","May","June","July","August","September","October","November","December"};
  
  Graph(float X1, float X2, float Y1, float Y2) {
    x1 = X1;
    x2 = X2;
    y1 = Y1;
    y2 = Y2;
    
    graphWidth = x2 - x1 - 2*graphSpace;
    //graphHeight = (y2 - y1 - (1+maxGraphs) * graphSpace) / maxGraphs;
    graphType = new int[maxGraphs];
    for (int i = 0; i < maxGraphs; i++)
      graphType[i] = -1;
    monthSelected = 0;
    lastClicked = 0;
  }
  
  void addGraphType(int genre) {
    if (graphType[currentSlot] != -1 && numOfGraphs >= maxGraphs)
      genres.toggle(graphType[currentSlot]);
    graphType[currentSlot] = genre;
    currentSlot = (currentSlot + 1) % maxGraphs;
    if (numOfGraphs < maxGraphs) 
        numOfGraphs++;
  }
  
  void removeGraphType(int genre) {
    for (int i = 0; i < maxGraphs; i++)
      if (graphType[i] == genre) {
        graphType[i] = -1;
        currentSlot = i;
        if (numOfGraphs > 0) 
          numOfGraphs--;
        return;
      }        
  }
  
  void clear() {
    numOfGraphs = 0;
    currentSlot = 0;
    for (int i = 0; i < maxGraphs; i++)
      graphType[i] = -1;
    monthSelected = 0;
  }
  
  void draw() {
    noFill();
    strokeWeight(1);
    stroke(175, 50);
    rectMode(CORNERS);
    rect(x1, y1, x2, y2);
    drawAxisLabels(x1, x2, y1);
    drawDataPointsFixed(All, filmTimeLine.sliderBarX1, filmTimeLine.sliderBarX2, 
        filmTimeLine.sliderBarY1, filmTimeLine.sliderBarY2);
    if (numOfGraphs == 0)
      return;
    graphHeight = (y2 - y1 - (1+numOfGraphs) * graphSpace) / numOfGraphs;
    float gX1, gX2, gY1, gY2;
    for (int i = 0, j = 0; j < maxGraphs; j++) {
      if (graphType[j] == -1)
        continue;
      gX1 = x1 + graphSpace;
      gX2 = gX1 + graphWidth;
      gY1 = y1 + (i+1) * graphSpace + i * graphHeight;
      gY2 = gY1 + graphHeight;
      noFill();
      strokeWeight(1);
      stroke(175, 50);
      rect(gX1, gY1, gX2, gY2);
      
      textAlign(CENTER);
      textSize(12);
      fill(255);
      String Genre = genreName[graphType[j]];
      float sWidth = textWidth(Genre);
      text(Genre, gX1+(gX2-gX1)/2.0, gY1+15);
      //println("Plotting " + genreName[graphType[i]] + " Releases...");
      drawDataLine(graphType[j], gX1, gX2, gY1, gY2);
      drawDataHighlight(graphType[j], gX1, gX2, gY1, gY2);
      drawDataMouseOver(graphType[j], gX1, gX2, gY1, gY2);
      drawDataRange(graphType[j], gX1, gX2, gY1, gY2);
      drawDateTicks(gX1, gX2, gY1, gY2);
      //noFill();
      //rect((gX2-gX1)/2 - sWidth/2 - 3, gY1+3, (gX2-gX1)/2 + sWidth/2 + 3, gY1+18);
      i++;
    }
  }//draw
  
  void drawAxisLabels(float X1, float X2, float Y1) {
    fill(255);
    textSize(12);
    textAlign(CENTER, CENTER);
    text("Number of Movie Releases per Month Over Time", (X1+X2)/2.0, Y1-12);
    textSize(9);
    text("Source: IMDB.com", X2-40, Y1-8);
    textAlign(LEFT, CENTER);
    if (monthSelected > 0 && monthSelected <= 12)
      text("Highlighting Releases in " + monthName[monthSelected-1], X1, Y1-8);
  }
  
  void drawDataRange(int genre, float X1, float X2, float Y1, float Y2) {
    fill(200);
    stroke(200);
    textSize(8);
    textAlign(RIGHT, BOTTOM);
    text(0, X1, Y2);
    textAlign(RIGHT, CENTER);
    float dataMax = 1085;
    if (genre != 18)
       dataMax = dataArray[genre].getMax();
    dataMax *= 1.1;
    float gap = 1;
    if (dataMax > 25)
      gap = (floor(dataMax/100.0) + 1) * 10;
    else if (dataMax > 10)
      gap = 5;
    int sections = int (dataMax / gap);
    for (int i = 1; i <= sections; i++) {
      float y = map(gap*i, 0, dataMax, Y2, Y1);
      text(nf(gap*i,0,0), X1-1, y-1);
      line(X1+2, y, X1-2, y);
    }
    //textAlign(RIGHT, TOP);
    //float y = map(gap*sections, 0, dataMax, Y2, Y1);
    //text(nf(gap*sections,0,0), X1, y);
    //line(X1+2, y, X1-2, y);
  }
    
    
  
  void drawDateTicks(float X1, float X2, float Y1, float Y2) {
    fill(200);
    stroke(200);
    textSize(8);
    textAlign(CENTER, TOP);
    float dateMin = filmTimeLine.getYearMin();
    float dateMax = filmTimeLine.getYearMax();
    int yearMin = int(dateMin);
    int yearMax = int(dateMax);
    float ratio = 91.0 / (dateMax - dateMin);
    int yearSplit = 1;
    if (ratio <= 2)
      yearSplit = 10;
    else if (ratio <= 4)
      yearSplit = 5;
    for (int yr = yearMin; yr <= yearMax; yr++) { 
      for (int m = 1; m <= 12; m++) {
        float date = yr+(m-1)/12.0;
        if (date < dateMin || date > dateMax)
          continue;
        float x = map(date, dateMin, dateMax, X1, X2); 
        if (m % 12 == 7 && yr % yearSplit == 0) {
          text(yr, x, Y2+3);
        }
        if ((m-1) % 3 == 0 && (dateMax - dateMin) * 2.0 <= 91.0)
          line(x, Y2, x, Y2+2);
        if (m == 1)
          line(x, Y2, x, Y2+4);
      }
    }
    //for zoomed view end points
    if ((dateMax - dateMin) * 2.0 <= 91.0) { 
      int monthNum = int(filmTimeLine.getMonthMin());
      if (monthNum != 7 && yearMin % yearSplit != 0)
        text(yearMin, X1, Y2);
      monthNum = int(filmTimeLine.getMonthMax());
      if (monthNum != 7 && yearMax % yearSplit != 0)
        text(yearMax, X2, Y2);
    }
        
  }
  
  float getValue(int genre, int yr, int mon) {
      if (cluster.cluster == 1) {
        return dataArray[genre].getCount(yr, mon);
      }
      float average = 0;
      int count = 0;
      int offset = (mon-1) % cluster.cluster;
      for (int m = mon - offset + 1; count < cluster.cluster || m <= 12; m++) {
        if (yr >= 2010 && m > 10)
          break;
        average += dataArray[genre].getCount(yr, m);
        count++;
      }
      if (count > 0)
        average /= count;
      return average;
  }
  
    // Draw the data as a series of points 
  void drawDataPoints(int genre, float X1, float X2, float Y1, float Y2) { 
    stroke(255, 100);
    //int monthMin = int(filmTimeLine.getMonthMin());
    //int monthMax = int(filmTimeLine.getMonthMax());
    float dateMin = filmTimeLine.getYearMin();
    float dateMax = filmTimeLine.getYearMax();
    float dataMax = 1085;
    if (genre != 18)
          dataMax = dataArray[genre].getMax();
    int yearMin = int(dateMin);
    int yearMax = int(dateMax);
    for (int yr = yearMin; yr <= yearMax; yr++) { 
      for (int m = 1; m <= 12; m++) {
        float date = yr+(m-1)/12.0;
        if (date < dateMin || date > dateMax)
          continue;
        float value = 0;
        if (genre == 18) //All genres: total sum
          for (int i = 0; i < 18; i++)
            value += getValue(i, yr, m);
        else
          value = getValue(genre, yr, m);
        //println("Count for " + yr + " " + m + " " + value);
        if (value > 0)
          strokeWeight(5);
        else strokeWeight(2);
        float x = map(date, dateMin, dateMax, X1, X2); 
        float y = map(value, 0, 1.1*dataMax, Y2, Y1); 
        point(x, y);
      } 
    } 
  }
  
    // Draw the data as a series of points 
  void drawDataPointsFixed(int genre, float X1, float X2, float Y1, float Y2) { 
    stroke(255, 100);
    //int monthMin = int(filmTimeLine.getMonthMin());
    //int monthMax = int(filmTimeLine.getMonthMax());
    float dateMin = filmTimeLine.yearMin;
    float dateMax = filmTimeLine.yearMax;
    float dataMax = 1085;
    if (genre != 18)
          dataMax = dataArray[genre].getMax();
    int yearMin = int(dateMin);
    int yearMax = int(dateMax);
    for (int yr = yearMin; yr <= yearMax; yr++) { 
      for (int m = 1; m <= 12; m++) {
        float date = yr+(m-1)/12.0;
        if (date < dateMin || date > dateMax)
          continue;
        float value = 0;
        if (genre == 18) //All genres: total sum
          for (int i = 0; i < 18; i++)
            value += getValue(i, yr, m);
        else
          value = getValue(genre, yr, m);
        //println("Count for " + yr + " " + m + " " + value);
        if (value > 0)
          strokeWeight(1);
        else strokeWeight(1);
        float x = map(date, dateMin, dateMax, X1, X2); 
        float y = map(value, 0, 1.1*dataMax, Y2, Y1); 
        point(x, y);
      } 
    } 
  }
  
      // Draw the data as a series of points 
  void drawDataLine(int genre, float X1, float X2, float Y1, float Y2) { 
    stroke(pieChartTotal.getColor(genre));
    strokeWeight(1);
    fill(pieChartTotal.getColor(genre));
    beginShape();
    vertex(X1, Y2);
    //int monthMin = int(filmTimeLine.getMonthMin());
    //int monthMax = int(filmTimeLine.getMonthMax());
    float dateMin = filmTimeLine.getYearMin();
    float dateMax = filmTimeLine.getYearMax();
    float dataMax = 1085;
    if (genre != 18)
          dataMax = dataArray[genre].getMax();
    int yearMin = int(dateMin);
    int yearMax = int(dateMax);
    for (int yr = yearMin; yr <= yearMax; yr++) { 
      for (int m = 1; m <= 12; m++) {
        float date = yr+(m-1)/12.0;
        if (date < dateMin || date > dateMax)
          continue;
        float value = 0;
        if (genre == 18) //All genres: total sum
          for (int i = 0; i < 18; i++)
            value += getValue(i, yr, m);
        else
          value = getValue(genre, yr, m);
        //println("Count for " + yr + " " + m + " " + value);
        //if (value > 0)
          //strokeWeight(5);
        //else strokeWeight(2);
        float x = map(date, dateMin, dateMax, X1, X2); 
        float y = map(value, 0, 1.1*dataMax, Y2, Y1); 
        vertex(x, y);
        if (m == monthSelected) {
          //strokeWeight(20);
          stroke(0);
          fill(255);
          ellipse(x, y, 10, 10);
        stroke(pieChartTotal.getColor(genre));
        strokeWeight(1);
        fill(pieChartTotal.getColor(genre));
          //strokeWeight(1);
        }
      } 
    }    
    vertex(X2, Y2);
    endShape(CLOSE); 
  }
  
  void drawDataHighlight(int genre, float X1, float X2, float Y1, float Y2) { 
    float dateMin = filmTimeLine.getYearMin();
    float dateMax = filmTimeLine.getYearMax();
    float dataMax = 1085;
    if (genre != 18)
          dataMax = dataArray[genre].getMax();
    int yearMin = int(dateMin);
    int yearMax = int(dateMax);
    for (int yr = yearMin; yr <= yearMax; yr++) { 
      for (int m = 1; m <= 12; m++) {
        float date = yr+(m-1)/12.0;
        if (date < dateMin || date > dateMax)
          continue;
        float value = 0;
        if (genre == 18) //All genres: total sum
          for (int i = 0; i < 18; i++)
            value += getValue(i, yr, m);
        else
          value = getValue(genre, yr, m);
        float x = map(date, dateMin, dateMax, X1, X2); 
        float y = map(value, 0, 1.1*dataMax, Y2, Y1); 
        if (m == monthSelected) {
          //strokeWeight(20);
          stroke(0);
          fill(255, 150);
          ellipse(x, y, 12, 12);
          //stroke(pieChartTotal.getColor(genre));
        }
      }
    }    
  }

  void drawDataMouseOver(int genre, float X1, float X2, float Y1, float Y2) { 
    float dateMin = filmTimeLine.getYearMin();
    float dateMax = filmTimeLine.getYearMax();
    float dataMax = 1085;
    if (genre != 18)
          dataMax = dataArray[genre].getMax();
    int yearMin = int(dateMin);
    int yearMax = int(dateMax);
    for (int yr = yearMin; yr <= yearMax; yr++) { 
      for (int m = 1; m <= 12; m++) {
        float date = yr+(m-1)/12.0;
        if (date < dateMin || date > dateMax)
          continue;
        float value = 0;
        if (genre == 18) //All genres: total sum
          for (int i = 0; i < 18; i++)
            value += getValue(i, yr, m);
        else
          value = getValue(genre, yr, m);
        float x = map(date, dateMin, dateMax, X1, X2); 
        float y = map(value, 0, 1.1*dataMax, Y2, Y1);
        float ratio = 200.0 / (dateMax - dateMin);
        if (ratio > 5)
          ratio = 5;
        if (cluster.cluster > 4 && ratio <= 3)
          ratio = 1;
        if (dist(mouseX, mouseY, x, y) < ratio) {
          if (mousePressed == true && millis()-lastClicked > 1000) {
            lastClicked = millis();      
            if (m != monthSelected)
              monthSelected = m;
            else
              monthSelected = 0;
          }
          strokeWeight(1);
          stroke(0);
          fill(pieChartTotal.getColor(genre));
          ellipse(x, y, 10, 10);
          fill(125,200);
          stroke(0);
          strokeWeight(1);
          rectMode(CORNERS);
          rect(x, y-3, x+90, y-35);
          fill(0);
          textAlign(LEFT);
          textSize(12);
          text(nf(value,0,1), x+5, y-20);
          textSize(10);
          fill(255);
          text("Releases", x+textWidth(nf(value,0,1))+12, y-20);
          text(monthName[m-1]+" "+yr, x+5, y-10);
        } 
      }
    }    
  }      
  
}//class
